package Task;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.*;
import java.sql.Date;
import java.util.*;

public class FiberTestParserV3 {
    private static final String DB_URL = "jdbc:mysql://wk339bf0531.vicp.fun:28862/jxjs_sc?useSSL=false&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "17371354127";

    // 定义要处理的文件目录（可根据需要修改）
    private static final String ROOT_DIRECTORY = "src/main/resources/data/2025/8";
    // 定义要处理的文件后缀（根据实际文件类型调整）
    private static final String FILE_EXTENSION = ".dat";

    private static class InfoInsertResult {
        Integer infoId;
        boolean isNew;
    }

    public static void main(String[] args) {
        // 循环处理文件夹中的所有文件
        processDirectory(ROOT_DIRECTORY);
    }

    /**
     * 处理指定目录下的所有文件（包括子目录）
     * @param directoryPath 要处理的目录路径
     */
    public static void processDirectory(String directoryPath) {
        File rootDir = new File(directoryPath);
        // 检查目录是否存在
        if (!rootDir.exists() || !rootDir.isDirectory()) {
            System.err.println("目录不存在或不是有效目录: " + directoryPath);
            return;
        }

        System.out.println("开始处理目录: " + directoryPath);
        // 递归遍历目录下的所有文件
        Collection<File> files = FileUtils.listFiles(
                rootDir,
                new String[]{FILE_EXTENSION.substring(1)}, // 去掉前缀"."，符合FileUtils的参数要求
                true // 是否包含子目录
        );

        if (files.isEmpty()) {
            System.out.println("目录下没有找到" + FILE_EXTENSION + "文件: " + directoryPath);
            return;
        }

        // 遍历每个文件并处理
        for (File file : files) {
            String filePath = file.getAbsolutePath();
            processSingleFile(filePath);
        }

        System.out.println("目录处理完成: " + directoryPath);
    }

    /**
     * 处理单个文件的静态方法，供目录遍历调用
     */
    public static void processSingleFile(String filePath) {
        // 检查文件是否存在
        File file = new File(filePath);
        if (!file.exists()) {
            System.err.println("文件不存在: " + filePath);
            return;
        }

        try {
            System.out.println("正在处理文件: " + filePath);

            try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
                // 检查文件是否已导入
                String checkSql = "SELECT 1 FROM import_file_log_test WHERE file_path = ?";
                PreparedStatement checkStmt = conn.prepareStatement(checkSql);
                checkStmt.setString(1, filePath);
                ResultSet rs = checkStmt.executeQuery();
                if (rs.next()) {
                    System.out.println("已导入，跳过: " + filePath);
                    return;
                }

                List<String> lines = FileUtils.readLines(file, "GBK");
                InfoInsertResult infoResult = parseAndInsertTestInfo(lines);
                if (infoResult.isNew) {
                    System.out.println("fiber_test_info 新增，准备插入明细数据: " + filePath);
                    List<FiberTestDataRow> dataRows = parseAndInsertTestData(lines, infoResult.infoId);
                    parseAndInsertTestStats(dataRows, infoResult.infoId);
                } else {
                    System.out.println("fiber_test_info 已存在，跳过明细数据导入: " + filePath);
                }

                // 记录已导入
                String insertLog = "INSERT INTO import_file_log_test (file_path) VALUES (?)";
                PreparedStatement logStmt = conn.prepareStatement(insertLog);
                logStmt.setString(1, filePath);
                logStmt.executeUpdate();

                System.out.println("文件处理完成: " + filePath);
            } catch (Exception e) {
                System.err.println("处理文件失败: " + filePath);
                e.printStackTrace();
            }
        } catch (Exception e) {
            System.err.println("程序执行异常: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 以下方法与原代码保持一致，省略重复注释
    private static InfoInsertResult parseAndInsertTestInfo(List<String> lines) throws SQLException {
        String reportType = lines.get(0).replace("\"", "");
        String testDate = lines.get(1).replace("\"", "");
        String testTime = lines.get(2).replace("\"", "");
        int envTemperature = Integer.parseInt(lines.get(3).replace("\"", ""));
        String envHumidity = lines.get(4).replace("\"", "");
        String sampleName = lines.get(5).replace("\"", "");
        double sampleLength = Double.parseDouble(lines.get(6).replace("\"", ""));
        String operator = lines.get(7).replace("\"", "");
        String machineModel = lines.get(8).replace("\"", "");
        int sampleCount = Integer.parseInt(lines.get(9).replace("\"", ""));
        String addLength = lines.get(10).replace("\"", "");
        String stretchSpeed = lines.get(11).replace("\"", "");
        String sampleFineness = lines.get(12).replace("\"", "");
        String forceDrop = lines.get(13).replace("\"", "");
        String constantElongation = lines.get(14).replace("\"", "");

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            String checkSql = "SELECT id FROM fiber_test_info WHERE test_date=? AND test_time=?";
            PreparedStatement checkStmt = conn.prepareStatement(checkSql);
            checkStmt.setDate(1, Date.valueOf(testDate));
            checkStmt.setTime(2, Time.valueOf(testTime));
            ResultSet rs = checkStmt.executeQuery();
            InfoInsertResult result = new InfoInsertResult();
            if (rs.next()) {
                result.infoId = rs.getInt("id");
                result.isNew = false;
                return result;
            }
            String sql = "INSERT INTO fiber_test_info (report_type, test_date, test_time, env_temperature, env_humidity, sample_name, sample_length, operator, machine_model, sample_count, add_length, stretch_speed, sample_fineness, force_drop, constant_elongation, create_time, update_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
            PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            pstmt.setString(1, reportType);
            pstmt.setDate(2, Date.valueOf(testDate));
            pstmt.setTime(3, Time.valueOf(testTime));
            pstmt.setInt(4, envTemperature);
            pstmt.setString(5, envHumidity);
            pstmt.setString(6, sampleName);
            pstmt.setDouble(7, sampleLength);
            pstmt.setString(8, operator);
            pstmt.setString(9, machineModel);
            pstmt.setInt(10, sampleCount);
            pstmt.setString(11, addLength);
            pstmt.setString(12, stretchSpeed);
            pstmt.setString(13, sampleFineness);
            pstmt.setString(14, forceDrop);
            pstmt.setString(15, constantElongation);
            pstmt.executeUpdate();
            ResultSet rs2 = pstmt.getGeneratedKeys();
            if (rs2.next()) {
                result.infoId = rs2.getInt(1);
                result.isNew = true;
                return result;
            }
            throw new SQLException("插入 fiber_test_info 失败");
        }
    }

    private static List<FiberTestDataRow> parseAndInsertTestData(List<String> lines, long infoId) throws SQLException {
        List<FiberTestDataRow> dataRows = new ArrayList<>();
        int startIdx = 10; // 明细数据起始行（前10行为基础信息）
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            String sql = "INSERT INTO fiber_test_data (test_info_id, test_number, break_strength, break_elongation, break_strength_index, break_elongation_rate, break_time, initial_modulus, elastic_modulus, elongation_strength, create_time, update_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            int insertCount = 0;
            for (int i = startIdx; i < lines.size(); i++) {
                String line = lines.get(i).trim();

                String[] parts = line.split(",");
//                System.out.println("parts.length: " + parts.length);
                if (parts.length == 9) { // 只处理9字段的有效数据行
                    FiberTestDataRow row = new FiberTestDataRow();
                    row.testNumber = (int) parseDouble(parts[0]);
                    row.breakStrength = parseDouble(parts[1]);
                    row.breakElongation = parseDouble(parts[2]);
                    row.breakStrengthIndex = parseDouble(parts[3]);
                    row.breakElongationRate = parseDouble(parts[4]);
                    row.breakTime = parseDouble(parts[5]);
                    row.initialModulus = parseDouble(parts[6]);
                    row.elasticModulus = parseDouble(parts[7]);
                    row.elongationStrength = parseDouble(parts[8]);

                    row.breakStrength = Math.round(row.breakStrength * 100.0) / 100.0;
                    row.breakElongation = Math.round(row.breakElongation * 100.0) / 100.0;
                    row.breakStrengthIndex = Math.round(row.breakStrengthIndex * 100.0) / 100.0;
                    row.breakElongationRate = Math.round(row.breakElongationRate * 100.0) / 100.0;
                    row.breakTime = Math.round(row.breakTime * 100.0) / 100.0;
                    row.initialModulus = Math.round(row.initialModulus * 100.0) / 100.0;
                    row.elasticModulus = Math.round(row.elasticModulus * 100.0) / 100.0;
                    row.elongationStrength = Math.round(row.elongationStrength * 100.0) / 100.0;

                    dataRows.add(row);
                    System.out.println("准备插入: test_info_id=" + infoId + ", test_number=" + row.testNumber);
                    pstmt.setLong(1, infoId);
                    pstmt.setInt(2, row.testNumber);
                    pstmt.setDouble(3, row.breakStrength);
                    pstmt.setDouble(4, row.breakElongation);
                    pstmt.setDouble(5, row.breakStrengthIndex);
                    pstmt.setDouble(6, row.breakElongationRate);
                    pstmt.setDouble(7, row.breakTime);
                    pstmt.setDouble(8, row.initialModulus);
                    pstmt.setDouble(9, row.elasticModulus);
                    pstmt.setDouble(10, row.elongationStrength);
                    pstmt.addBatch();
                    insertCount++;
                }
            }
            pstmt.executeBatch();
            System.out.println("批量插入完成，共插入 " + insertCount + " 条数据");
        }
        return dataRows;
    }

    private static void parseAndInsertTestStats(List<FiberTestDataRow> dataRows, Integer infoId) throws SQLException {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            String sql = "INSERT INTO qualitativetaskdetail_test (item, units, indicators, referenceValueMin, referenceValueMax, f9ce, ft769) VALUES (?, ?, ?, ?, ?, ?, ?)";
            PreparedStatement pstmt = conn.prepareStatement(sql);

            insertFieldStats(pstmt, "断裂强力", "N", dataRows, infoId);
            insertFieldStats(pstmt, "断裂伸长", "mm", dataRows, infoId);
            insertFieldStats(pstmt, "断裂强度", "cN/dtex", dataRows, infoId);
            insertFieldStats(pstmt, "断裂伸长率", "%", dataRows, infoId);
            insertFieldStats(pstmt, "断裂时间", "s", dataRows, infoId);
            insertFieldStats(pstmt, "初始模量", "cN/dtex", dataRows, infoId);
            insertFieldStats(pstmt, "弹性模量", "cN/dtex", dataRows, infoId);
            insertFieldStats(pstmt, "定伸长强力", "cN/dtex", dataRows, infoId);

            pstmt.executeBatch();
            System.out.println("qualitativetaskdetail_test 数据插入完成");
        }
    }

    private static void insertFieldStats(PreparedStatement pstmt, String item, String units, List<FiberTestDataRow> dataRows, Integer infoId) throws SQLException {
        double avg = avg(dataRows.stream().mapToDouble(r -> getFieldValue(r, item)).toArray());
        double max = dataRows.stream().mapToDouble(r -> getFieldValue(r, item)).max().orElse(0.0);
        double min = dataRows.stream().mapToDouble(r -> getFieldValue(r, item)).min().orElse(0.0);

        pstmt.setString(1, item);
        pstmt.setString(2, units);
        pstmt.setDouble(3, avg);
        pstmt.setDouble(4, min);
        pstmt.setDouble(5, max);
        pstmt.setInt(6, infoId);
        pstmt.setString(7, "合格");
        pstmt.addBatch();
    }

    private static double getFieldValue(FiberTestDataRow row, String fieldName) {
        switch (fieldName) {
            case "break_strength":
            case "断裂强力": return row.breakStrength;
            case "break_elongation":
            case "断裂伸长": return row.breakElongation;
            case "break_strength_index":
            case "断裂强度": return row.breakStrengthIndex;
            case "break_elongation_rate":
            case "断裂伸长率": return row.breakElongationRate;
            case "break_time":
            case "断裂时间": return row.breakTime;
            case "initial_modulus":
            case "初始模量": return row.initialModulus;
            case "elastic_modulus":
            case "弹性模量": return row.elasticModulus;
            case "elongation_strength":
            case "定伸长强力": return row.elongationStrength;
            default: return 0.0;
        }
    }

    private static double parseDouble(String s) {
        try {
            return Double.parseDouble(s);
        } catch (Exception e) {
            return 0.0;
        }
    }

    private static double avg(double[] arr) {
        if (arr.length == 0) return 0.0;
        BigDecimal sum = BigDecimal.ZERO;
        for (double d : arr) {
            sum = sum.add(BigDecimal.valueOf(d));
        }
        return sum.divide(BigDecimal.valueOf(arr.length), 2, RoundingMode.HALF_UP).doubleValue();
    }

    static class FiberTestDataRow {
        int testNumber;
        double breakStrength;
        double breakElongation;
        double breakStrengthIndex;
        double breakElongationRate;
        double breakTime;
        double initialModulus;
        double elasticModulus;
        double elongationStrength;
    }
}